package cn.com.wxd.common.security;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.util.Random;
import org.apache.commons.codec.binary.Hex; 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
/**
 * Title:PassWordUtil.java
 * Description:cn.com.wxd.util.dao
 * 
 * Company: Amumu管理平台
 * Copyright: Copyright (c) 2015
 * All right reserved.
 * Created time: 2015-10-27 上午9:55:19
 *
 * @author WangXuDong
 * @version 1.0
 * 密码工具类
 */ 
public class PasswordUtil {
	private static final Logger log = LoggerFactory.getLogger(PasswordUtil.class);
	/**
	 * 生成含有随机盐的MD5密码 
	 * @param password 明文密码
	 * @return 加密后的密码
	 */
	public static String generate(String password) {
		Random r = new Random();
		StringBuilder sb = new StringBuilder(16);
		sb.append(r.nextInt(99999999)).append(r.nextInt(99999999));
		int len = sb.length();
		if (len < 16) {
			for (int i = 0; i < 16 - len; i++) {
				sb.append("0");
			}
		}
		String salt = sb.toString();
		password = md5Hex(password + salt); //加盐后加密
		char[] cs = new char[48];
		for (int i = 0; i < 48; i += 3) {   //把盐按照一定的规则存入加密码中
			cs[i] = password.charAt(i / 3 * 2);  //把加密后的密码按一定规则排列
			char c = salt.charAt(i / 3);
			cs[i + 1] = c;
			cs[i + 2] = password.charAt(i / 3 * 2 + 1);
		}
		String superPassword = new String(cs);
		return superPassword;
	}  
	/**
	 * 校验密码是否正确 
	 * @param password 明文密码
	 * @param md5 加密后含随机盐的的密码
	 * @return 是否一样
	 */
	public static boolean verify(String password, String md5) {
		char[] cs1 = new char[32];
		char[] cs2 = new char[16];
		for (int i = 0; i < 48; i += 3) {
			cs1[i / 3 * 2] = md5.charAt(i);
			cs1[i / 3 * 2 + 1] = md5.charAt(i + 2);
			cs2[i / 3] = md5.charAt(i + 1);
		}
		String salt = new String(cs2);
		boolean bool =md5Hex(password + salt).equals(new String(cs1));
		return bool;
	}
	/**
	 * 将密码加密成Base64位
	 * @param str 明文密码
	 * @return 加密后的密码
	 */
	public static String encrypeBase64(String proPwd) {  
		byte[] b = null;  
		String s = null;  
		try {  
			b = proPwd.getBytes("utf-8");  
		} catch (UnsupportedEncodingException e) {  
			System.out.println(e.getMessage());
		}  
		if (b != null) {  
			s = new BASE64Encoder().encode(b);  
		}  
		return s;  
	}  

	/**
	 * 解密base64位的密码
	 * @param s base64位密码
	 * @return 明文密码
	 */
	public static String decipBase64(String pwd) {  
		byte[] b = null;  
		String result = null;  
		if (pwd != null) {  
			BASE64Decoder decoder = new BASE64Decoder();  
			try {  
				b = decoder.decodeBuffer(pwd);  
				result = new String(b, "utf-8");  
			} catch (Exception e) {
				log.error("",e);
			}  
		}  
		return result;  
	}
	/**
	 * 使用SHA加密(KEY_SHA = "SHA";)
	 * @param data
	 * @return
	 * @throws Exception
	 */
	public static byte[] encryptSHA(byte[] data) throws Exception { 
		MessageDigest sha = MessageDigest.getInstance("SHA");
		sha.update(data);
		return sha.digest();
	}
	/**
	 * 获取十六进制字符串形式的MD5摘要 
	 * @param src
	 * @return
	 */
	private static String md5Hex(String src) {
		try {
			MessageDigest md5 = MessageDigest.getInstance("MD5");
			byte[] bs = md5.digest(src.getBytes());
			String md5Password = new String(new Hex().encode(bs));
			return  md5Password;
		} catch (Exception e) {
			log.error(e.getMessage(),e);
			return null;
		}
	}
	/**
	 * 自定义加密
	 * @param pwd 明文密码
	 * @param key 8位随机KEY(如：KEY12U2M)，但必须与解密接口的KEY一致
	 * @return 生成的加密密码
	 */
	public static String customEncrypt(String pwd,String key){
		try {
			if(key.length()!=8){
				try {
					throw  new Exception("key密钥不正确");
				} catch (Exception e) {
					log.error(e.getMessage(),e);
					return "";
				}
			}
			String mkey = md5Hex(key.toUpperCase()).toUpperCase();
			if(mkey.length()%2==0){
				mkey = mkey.substring(0,mkey.length()/2);			
			}else{
				mkey = mkey.substring(0,mkey.length()/2+1);	
			}

			String bpwd = encrypeBase64(pwd);
			String a = mkey.substring(0,(mkey.length()-((mkey.length())/2)))
					+bpwd
					+mkey.substring((mkey.length()-((mkey.length())/2)));

			int num = 0;
			String miaoshu = "";
			if(mkey.length()%2==0){
				num = mkey.length()/2;
				miaoshu = "E";
			}else{
				num = mkey.length()/2+1;
				miaoshu = "O";
			}

			return encrypeBase64(a+miaoshu+num);
		} catch (Exception e) {
			log.error(e.getMessage(),e);
			return "";
		}
	}
	/**
	 * 自定义解密
	 * @param pwd 被加密密码
	 * @param key 加密时使用的KEY密钥(如：KEY12U2M)
	 * @return 明文密码
	 */
	public static String customDeciphe(String pwd,String key){
		try {
			pwd = decipBase64(pwd);
			if(key.length()!=8){
				try {
					throw  new Exception("key密钥不正确");
				} catch (Exception e) {
					log.error(e.getMessage(),e);
					return "";
				}
			}
			String mkey = md5Hex(key.toUpperCase()).toUpperCase();
			if(mkey.length()%2==0){
				mkey = mkey.substring(0,mkey.length()/2);			
			}else{
				mkey = mkey.substring(0,mkey.length()/2+1);	
			}
			String inum = pwd.substring(pwd.length()-1);
			String miaoshu = pwd.substring(pwd.length()-2,pwd.length()-1);
			int num=0;
			try {
				num = Integer.valueOf(inum).intValue();
				if(!miaoshu.equals("O")&&!miaoshu.equals("E")){
					throw new Exception("密码格式错误");
				}
			} catch (Exception e) {
				try {
					throw new Exception("密码格式错误");
				} catch (Exception e1) {
					log.error(e.getMessage(),e);
					return "";
				}
			}
			String password = "";
			String ikey1 = pwd.substring(0,num);
			String ikey2 = "";
			password = pwd.substring(num);
			if(miaoshu.equals("O")){
				ikey2 = pwd.substring(pwd.length()-num-1);
				password = password.substring(0,password.length()-num-1);
			}else{
				ikey2 = pwd.substring(pwd.length()-num-2);
				password = password.substring(0,password.length()-num-2);
			}
			if(!((ikey1+ikey2).substring(0, (ikey1+ikey2).length()-2)).equals(mkey)){
				try {
					throw new Exception("key密钥或密码错误");
				} catch (Exception e) {
					log.error(e.getMessage(),e);
					return "";
				}
			}
			return decipBase64(password);
		} catch (Exception e) {
			log.error(e.getMessage(),e);
			return "";
		}
	}
}
